/*
 * Copyright (c) 2020 pig4cloud Authors. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.zyd.blog.framework.config.security.config;

import cn.hutool.core.util.ArrayUtil;
import com.zyd.blog.framework.config.security.component.PermitAllUrlProperties;
import com.zyd.blog.framework.config.security.component.PigBearerTokenExtractor;
import com.zyd.blog.framework.config.security.component.ResourceAuthExceptionEntryPoint;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.MessageSource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.support.ReloadableResourceBundleMessageSource;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
import org.springframework.security.config.annotation.web.configurers.HeadersConfigurer;
import org.springframework.security.oauth2.server.resource.introspection.OpaqueTokenIntrospector;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
import org.springframework.stereotype.Component;

import java.util.Locale;
import java.util.stream.Collectors;

/**
 * @author lengleng
 * @date 2022-06-04
 *
 * 资源服务器认证授权配置
 * 这个配置类，完成的工作：
 * 				 认证失败处理
 * 				 白名单认证过滤
 * 				 请求的token校验
 * 				 从请求中获取用户信息，注入上下文
 * 涉及请求的校验：
 * 		对于有认证的请求，获取用户信息注入上下文
 * 		对于未认证的请求，可过滤白名单，其余不允许访问
 */
@Slf4j
//@RequiredArgsConstructor
@Component
public class PigResourceServerConfiguration {

	//认证错误处理返回信息：4xx
	@Autowired
	protected  ResourceAuthExceptionEntryPoint resourceAuthExceptionEntryPoint;

	//允许的url路径：目前只提供配置文件形式
	@Autowired
	private  PermitAllUrlProperties permitAllUrl;

	//配置除了被忽略的请求url，请求头的信息必须配置BearerToken或者携带assess_token
	@Autowired
	private  PigBearerTokenExtractor pigBearerTokenExtractor;

	//都有配置的话，从redis获取token信息，看看是否存在
	@Autowired
	private  OpaqueTokenIntrospector customOpaqueTokenIntrospector;

	public PigResourceServerConfiguration() {
	}

	@Bean
	public MessageSource securityMessageSource() {
		ReloadableResourceBundleMessageSource messageSource = new ReloadableResourceBundleMessageSource();
		messageSource.addBasenames("classpath:i18n/errors/messages");
		messageSource.setDefaultLocale(Locale.CHINA);
		return messageSource;
	}
	@Bean
	@Order(Ordered.HIGHEST_PRECEDENCE)
	SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
		http.authorizeRequests(authorizeRequests -> authorizeRequests
						.antMatchers(ArrayUtil.toArray(permitAllUrl.getUrls(), String.class))
						.authenticated()
						.anyRequest()
						.permitAll())
				.oauth2ResourceServer(
						oauth2 -> oauth2.opaqueToken(token -> token.introspector(customOpaqueTokenIntrospector))
								.authenticationEntryPoint(resourceAuthExceptionEntryPoint)
								.bearerTokenResolver(pigBearerTokenExtractor))
				.headers()
				.frameOptions()
				.disable()
				.and()
				.csrf()
				.disable();

		return http.build();
	}


}
